package com.mh.mh.netty.closechannel;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.CharsetUtil;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;

/**
 * 通用handler，处理IO事件
 * SimpleChannelInboundHandler 服务端用的
 * @author Administrator
 */
@Slf4j
@ChannelHandler.Sharable// Sharable 为了线程安全
public class HandlerServerHelloClose extends ChannelInboundHandlerAdapter {

    private static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    private static final Map<ChannelId, Integer> deviceIdMap = new HashMap<ChannelId, Integer>();
    private static final Map<String, ChannelId> map = new HashMap<String, ChannelId>();
    public static ChannelGroup getChannels() {return channels;}
    public static Map getMap() {return map;}
    public static Map<ChannelId, Integer> getDeviceIdMap(){
        return deviceIdMap;
    }


    /**
     * 只在第一次连接的时候调用
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 这里就是添加了所有正在运行的channel，如果断开连接，就是移除一个channel
        channels.add(ctx.channel());
    }


    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf in = (ByteBuf) msg;
        System.out.println("收到客户端发来的消息"+in.toString(CharsetUtil.UTF_8));
        ChannelId id = ctx.channel().id();
        map.put(in.toString(CharsetUtil.UTF_8), id);
        deviceIdMap.put(id, (int) Math.random());

        ctx.writeAndFlush(Unpooled.copiedBuffer("你好，我是服务端，我已收到你的消息", CharsetUtil.UTF_8));
    }

//    @Override
//    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
//        /**
//         * 处理IO异常
//         */
//        cause.printStackTrace();
//        ctx.close();
//    }


    /**
     * 心跳监控
     * @param ctx
     * @param evt
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {

        ChannelId channelId = ctx.channel().id();
        // 超时检测
        if(evt instanceof IdleStateEvent){
            IdleStateEvent event = (IdleStateEvent) evt;
            // 这里判断，是读超时，还是写超时
            if(event.state() == IdleState.READER_IDLE){

                log.info("读超时.......");

				for(String key : map.keySet()){
					System.out.println("mac key >> "+key);
				}

				for(ChannelId id : deviceIdMap.keySet()){
					System.out.println("channel key >> "+id.toString());
				}

            }
        }

    }


    /**
     * 断开连接，从map中去掉mac
     * 先掉线，再断开
     * 连接断开时，触发动作
     * @param ctx
     * @throws Exception
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        Channel incoming = ctx.channel();
        log.info("客户端"+incoming.remoteAddress()+"已断开");

        // 更加channelid删除deviceid
        ChannelId channelId = ctx.channel().id();
        deviceIdMap.remove(channelId);
        log.info("移除deviceIdMap..."+channelId);

        for(String key : map.keySet()){
            if(map.get(key).equals(channelId)){
                map.remove(key);
                log.info("移除map..."+key);
                log.info("执行下线操作");
//                deviceHelper.offLine(key);
            }
        }

        channels.remove(incoming);
//        ctx.channel().close();
        ctx.close();
    }


    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("client 掉线......");
    }


}
